using System;

namespace Headspring.Training.Core.Model
{
	public class WorkOrderStatus
	{
		public static readonly WorkOrderStatus Assigned = new WorkOrderStatus(
			"ASD", "Assigned", "Assigned", 2);

		public static readonly WorkOrderStatus Cancelled = new WorkOrderStatus(
			"CAN", "Cancelled", "Cancelled", 5);

		public static readonly WorkOrderStatus Complete = new WorkOrderStatus(
			"CMP", "Complete", "Complete", 4);

		public static readonly WorkOrderStatus Draft = new WorkOrderStatus(
			"DFT", "Draft", "Draft", 1);

		public static readonly WorkOrderStatus InProgress =
			new WorkOrderStatus("IPG", "InProgress", "In Progress", 3);

		public static readonly WorkOrderStatus None = new WorkOrderStatus(
			"", "", " ", 0);

		private readonly string _code;
		private readonly string _key;

		protected WorkOrderStatus()
		{
		}

		protected WorkOrderStatus(string code, string key, string friendlyName,
		                          byte sortBy) : this()
		{
			_code = code;
			_key = key;
			FriendlyName = friendlyName;
			SortBy = sortBy;
		}

		public string Code
		{
			get { return _code; }
		}

		public string Key
		{
			get { return _key; }
		}

		public string FriendlyName { get; set; }

		public byte SortBy { get; set; }

		public static WorkOrderStatus[] GetAllItems()
		{
			return new[]
			       	{
			       		Draft,
			       		Assigned,
			       		InProgress,
			       		Complete,
			       		Cancelled
			       	};
		}

		public override bool Equals(object obj)
		{
			var code = obj as WorkOrderStatus;
			if (code == null) return false;

			if (!GetType().Equals(obj.GetType())) return false;

			return _code.Equals(code.Code);
		}

		public override string ToString()
		{
			return FriendlyName;
		}

		public override int GetHashCode()
		{
			return _code.GetHashCode();
		}

		public bool IsEmpty()
		{
			return Code == "";
		}

		public static WorkOrderStatus FromCode(string code)
		{
			WorkOrderStatus[] items = GetAllItems();
			WorkOrderStatus match =
				Array.Find(items,
				           delegate(WorkOrderStatus instance) { return instance.Code == code; });

			if (match == null)
			{
				Logger.Warn(typeof (WorkOrderStatus),
				            string.Format("WorkOrderStatusCode code {0} out of range.", code));
				match = None;
			}

			return match;
		}

		public static WorkOrderStatus FromKey(string key)
		{
			if (key == null)
			{
				throw new NotSupportedException(
					"Finding a WorkOrderStatusCode for a null key is not supported");
			}

			WorkOrderStatus[] items = GetAllItems();
			WorkOrderStatus match = Array.Find(items,
			                                   delegate(WorkOrderStatus instance)
			                                   	{
			                                   		return
			                                   			(instance.Key.Equals(key,
			                                   			                     StringComparison
			                                   			                     	.
			                                   			                     	InvariantCultureIgnoreCase));
			                                   	});

			if (match == null)
			{
				throw new ArgumentOutOfRangeException(
					string.Format("Key '{0}' is not a valid key for {1}", key,
					              typeof (WorkOrderStatus).Name));
			}

			return match;
		}

		public static WorkOrderStatus Parse(string name)
		{
			return FromKey(name);
		}
	}
}